package org.tote.model;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.tote.util.Constant;

@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User implements Serializable {

	private static final long serialVersionUID = 2930046023024753021L;

	@Id
	@Column(name = "id", updatable = false)
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "username")
	private String username;

	@Column(name = "password")
	private String password;

	@Column
	private Integer status;

	@Column(name = "fullname_ru")
	private String fullnameRu;

	@Column(name = "fullname_en")
	private String fullnameEn;

	@Column(name = "date_registered", insertable = false, updatable = false)
	@Temporal(TemporalType.TIMESTAMP)
	private Date dateRegistered;

	@Column(name = "token")
	private String token;

	@Column(name = "locale")
	private String locale;

	@Column(name = "location")
	private String location;

	@Column(name = "email")
	private String email;

	@Column(name = "phone")
	private String phone;

	@Lob
	@Column(name = "avatar")
	private byte[] avatar;

	@Column(name = "avatar_ext")
	private String avatarType;

	@Column(name = "updtime")
	@Temporal(TemporalType.TIMESTAMP)
	private Date updTime;

	@ManyToOne
	@JoinColumn(name = "upduser")
	private User updUser;

	@OneToMany(mappedBy = "updUser") //, fetch = FetchType.LAZY)
	//@Cascade({ org.hibernate.annotations.CascadeType.DELETE })
	private List<User> childUsers;

	@OneToMany(mappedBy = "user", orphanRemoval = true) //, fetch = FetchType.LAZY
	private List<Role> roles;

	public User() {
	}

	public User(Long id, String name) {
		this.id = id;
		this.fullnameEn = name;
		this.fullnameRu = name;
	}

	public User(User user) {
		this.id = user.id;
		this.username = user.username;
		this.password = user.password;
		this.status = user.status;
		this.avatar = user.avatar;
		this.avatarType = user.avatarType;
		this.dateRegistered = user.dateRegistered;
		this.token = user.token;
		this.fullnameEn = user.fullnameEn;
		this.fullnameRu = user.fullnameRu;
		this.locale = user.locale;
		this.location = user.location;
		this.email = user.email;
		this.phone = user.phone;
		this.updTime = user.updTime;
		this.updUser = user.updUser;
		this.childUsers=user.childUsers;
		this.roles=user.roles;
	}

	public UserLight getAsUserLight() {
		UserLight userLight = new UserLight();
		userLight.setId(id);
		userLight.setName(getName());
		return userLight;
	}

	public String getName() {
		return Constant.getMessage(locale, fullnameRu, fullnameEn);
	}

	public void setName(String name) {
		fullnameRu = name;
		fullnameEn = name;
	}

	public Boolean getEnabled() {
		return status != null && status == Constant.STATUS_READY ? true : false;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public byte[] getAvatar() {
		return avatar;
	}

	public void setAvatar(byte[] avatar) {
		this.avatar = avatar;
	}

	public String getAvatarType() {
		return avatarType;
	}

	public void setAvatarType(String avatarType) {
		this.avatarType = avatarType;
	}

	public Integer getStatus() {
		return status;
	}

	public void setStatus(Integer status) {
		this.status = status;
	}

	public String getFullnameRu() {
		return fullnameRu;
	}

	public void setFullnameRu(String fullnameRu) {
		this.fullnameRu = fullnameRu;
	}

	public String getFullnameEn() {
		return fullnameEn;
	}

	public void setFullnameEn(String fullnameEn) {
		this.fullnameEn = fullnameEn;
	}

	public Date getDateRegistered() {
		return dateRegistered;
	}

	public void setDateRegistered(Date dateRegistered) {
		this.dateRegistered = dateRegistered;
	}

	public String getLocale() {
		return locale;
	}

	public void setLocale(String locale) {
		this.locale = locale;
	}

	public String getLocation() {
		return location;
	}

	public void setLocation(String location) {
		this.location = location;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public Date getUpdTime() {
		return updTime;
	}

	public void setUpdTime(Date updTime) {
		this.updTime = updTime;
	}

	public User getUpdUser() {
		return updUser;
	}

	public void setUpdUser(User updUser) {
		this.updUser = updUser;
	}

	public List<User> getChildUsers() {
		return childUsers;
	}

	public void setChildUsers(List<User> childUsers) {
		this.childUsers = childUsers;
	}

	public List<Role> getRoles() {
		return roles;
	}

	public void setRoles(List<Role> roles) {
		this.roles = roles;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + Arrays.hashCode(avatar);
		result = prime * result + ((avatarType == null) ? 0 : avatarType.hashCode());
		result = prime * result + ((dateRegistered == null) ? 0 : dateRegistered.hashCode());
		result = prime * result + ((email == null) ? 0 : email.hashCode());
		result = prime * result + ((fullnameEn == null) ? 0 : fullnameEn.hashCode());
		result = prime * result + ((fullnameRu == null) ? 0 : fullnameRu.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((locale == null) ? 0 : locale.hashCode());
		result = prime * result + ((location == null) ? 0 : location.hashCode());
		result = prime * result + ((password == null) ? 0 : password.hashCode());
		result = prime * result + ((phone == null) ? 0 : phone.hashCode());
		result = prime * result + ((status == null) ? 0 : status.hashCode());
		result = prime * result + ((token == null) ? 0 : token.hashCode());
		result = prime * result + ((updTime == null) ? 0 : updTime.hashCode());
		result = prime * result + ((updUser == null) ? 0 : updUser.hashCode());
		result = prime * result + ((username == null) ? 0 : username.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		User other = (User) obj;
		if (!Arrays.equals(avatar, other.avatar)) return false;
		if (avatarType == null) {
			if (other.avatarType != null) return false;
		} else if (!avatarType.equals(other.avatarType)) return false;
		if (dateRegistered == null) {
			if (other.dateRegistered != null) return false;
		} else if (!dateRegistered.equals(other.dateRegistered)) return false;
		if (email == null) {
			if (other.email != null) return false;
		} else if (!email.equals(other.email)) return false;
		if (fullnameEn == null) {
			if (other.fullnameEn != null) return false;
		} else if (!fullnameEn.equals(other.fullnameEn)) return false;
		if (fullnameRu == null) {
			if (other.fullnameRu != null) return false;
		} else if (!fullnameRu.equals(other.fullnameRu)) return false;
		if (id == null) {
			if (other.id != null) return false;
		} else if (!id.equals(other.id)) return false;
		if (locale == null) {
			if (other.locale != null) return false;
		} else if (!locale.equals(other.locale)) return false;
		if (location == null) {
			if (other.location != null) return false;
		} else if (!location.equals(other.location)) return false;
		if (password == null) {
			if (other.password != null) return false;
		} else if (!password.equals(other.password)) return false;
		if (phone == null) {
			if (other.phone != null) return false;
		} else if (!phone.equals(other.phone)) return false;
		if (status == null) {
			if (other.status != null) return false;
		} else if (!status.equals(other.status)) return false;
		if (token == null) {
			if (other.token != null) return false;
		} else if (!token.equals(other.token)) return false;
		if (updTime == null) {
			if (other.updTime != null) return false;
		} else if (!updTime.equals(other.updTime)) return false;
		if (updUser == null) {
			if (other.updUser != null) return false;
		} else if (!updUser.equals(other.updUser)) return false;
		if (username == null) {
			if (other.username != null) return false;
		} else if (!username.equals(other.username)) return false;
		return true;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + ", status=" + status + "]";
	}
}
